package com.example.emos.wx.user.shiro;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;


/**
 * JWT工具类
 *
 * @Author YinXi
 * @Versin 1.0.0
 * @Date 2023/7/27
 */
@Component
@Slf4j
public class JwtUtil {
    /**
     * 密钥
     */
    @Value("${emos.jwt.secret}")
    private String secret;
    /**
     * 过期时间（天）
     */
    @Value("${emos.jwt.expire}")
    private int expire;

    /**
     * 创建Token令牌
     *
     * @param userId 用户的id
     * @return 一个Token字符串
     */
    public String createToken(int userId) {
        //设置过期时间，使用hutool中的DateUtil的offset偏移方法，第一个参数是当前日期，第二个偏移时间的单位这里为天，第三个参数是偏移的量为5天
        //按照当前日期偏移的天数
        Date data = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, 5);
        //按照密钥加密
        Algorithm algorithm = Algorithm.HMAC256(secret);
        //执行加密和创建JWT字符串
        JWTCreator.Builder builder = JWT.create();
        //绑定相关信息
        builder.withClaim("userId", userId)
                .withExpiresAt(data);
        //生成的jwt
        String jwt = builder.sign(algorithm);
        return jwt;
    }

    /**
     * 从JWT中获取用户的id
     *
     * @return 用户的id值
     */
    public int getUserIdFromJwt(String jwt) {
        //对jwt进行解码
        DecodedJWT jwtDecoded = JWT.decode(jwt);
        //获取Claim
        Claim userClaim = jwtDecoded.getClaim("userId");
        //获取具体的Userid
        int userId = userClaim.asInt();
        return userId;
    }

    /**
     * 验证JWT，如果JWT成功验证无需返回否则会抛出RuntimeException下的异常
     *验证时会拿密钥验证看这个Token是不是按这个密钥加密的然后看是否过期
     * @param jwt 要验证的令牌字符串
     */
    public void verifierToken(String jwt) {
        //创建算法对象
        Algorithm algorithm = Algorithm.HMAC256(secret);
        //使用算法对象进行解密并存储在验证对象
        JWTVerifier verifier = JWT.require(algorithm).build();
        //使用验证方法进行验证
        verifier.verify(jwt);
    }
}
